閱讀今天的文章前,先回顧一下昨天的學習,回答看看:
- TypeScript 中有哪些資料型別呢?
如果有點不清楚答案的話,可以看看 Day05 的文章喔!
今天我們要來探討 TS 的原始型別(Primitive Types),包括數字(number)、字串(string)、布林值(boolean)、undefined、null和 symbol,這些型別都是原生JS 的資料型別,在 TS 中也完全支援。
和 JS 一樣,TypeScript 所有數字都是浮點數,型別為 number,除了支援 10 進制和 16 進制,也支援 ES6 的 2 進制和 8 進制的最新寫法。
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
// ES6 中的 2 進制表示法
let binaryLiteral: number = 0b1010;
// ES6 中的 8 進制表示法
let octalLiteral: number = 0o744;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;
轉譯成 ES5 的 JS 後會變成:
var decLiteral = 6;
var hexLiteral = 0xf00d;
// ES6 的 2進制編譯成 10進制數字
var binaryLiteral = 10;
// ES6 的 8進制編譯成 10進制數字
var octalLiteral = 484;
var notANumber = NaN;
var infinityNumber = Infinity;
和JS一樣可以使用雙引號和單引號表示字串
let name1:string = 'bob'
let name2:string = "bob"
轉譯成 ES5 的 JS 後會變成:
var name1 = 'bob'
var name2 = "bob"
TS中也可以使用 ES6 的模板字串(template literal),同樣使用反引號包住字串內容,並透過 $ 嵌入變數
let myName: string = 'Tom'
let myAge: number = 25
let sentence: string = `Hello, my name is ${myName}.
I'll be ${myAge + 1} years old next month.`
轉譯成 ES5 的 JS 後會變成:
var myName = 'Tom';
var myAge = 25;
var sentence = "Hello, my name is " + myName + ".\nI'll be " + (myAge + 1) + " years old next month.";
即簡單的true/false值。
let isDone: boolean = false
轉譯成 ES5 的 JS 後會變成:
var isDone = false
和 JS 一樣,在TS 中 undefined 和 null 兩者各自為一資料型別。null 和 undefined 基本上意思都是「無效」的值,但仍有些許不同。
先讓我們先來複習一下 JS 中使用 undefined 和 null的使用差異吧!
undefined 意思是變數沒有被宣告,或者是已經宣告了,但是沒有賦值。
常見使用情境如下:
(1)宣告一個變數,但沒有賦值
let a
console.log(a) //undefined
這時候 a 就會自動被賦值為 undefined
(2) 物件不存在的屬性或陣列不存在的元素
let obj = {}
console.log(obj.foo) //undefined
let arr = []
console.log(arr[0]) //undefined
(3) 函式定義參數,但執行時沒有傳入參數值
//函式定義了參數 a
function fn(a) {
console.log(a); // undefined
}
fn(); //執行時未傳入參數值
這時候 a 就是一個原始的、未被賦值的變數
null 表示「空值」或「曾經有值但現在沒有了」,使用在宣告了變數,但又不想讓它是未定義的狀態,因此,人為設置此變數為「空值」。
常見使用情境例如:
(1)釋放物件的記憶體內存
let obj = { a: 1, b:2 }
obj = null; // 釋放物件的記憶體指向
console.log(obj) // null
關於 Null 和 Undefined 在 JS 中的差別可看 stackoverflow這篇解釋有更詳細的說明。
let u: undefined = undefined;
let n: null = null;
預設情况下,null 和 undefined 是所有資料型別的的子型別,也就是說,可以把null 和 undefined 賦值給其他型別的變數。
舉個例子來說:
let num: number;
let str: string;
// 可以賦值 null 或 undefined 給其他資料型別如:數字、字串的變數
num = null;
str = undefined;
// Note: 要在 strictNullChecks: false 情況下
但要注意的是,上面程式碼要成立,strictNullChecks 要是 false才行。實際上,預設設定strictNullChecks 是 false,所以預設狀況下不用做調整。
但倘若 strictNullChe存在每種資料型別中(如下圖 null 和 undefined 會獨立出來成為一特殊值)。
這時候,null 只能賦值給 null 和 any,而 undefined 同理,只能賦值給 undefined 和 any (這裡會有一個例外是 undefined 也能賦值給 void)。
let num: number;
num = 123; // OK
num = null; // Error
num = undefined; // Error
let str: string;
str = 'Kira'; // OK
str = null; // Error
str = undefined; // Error
let name: any;
name = undefined // OK
name = null // OK
let age: undefined;
age = undefined // OK
age = null // Error
age = 123 // Error
let spot: null;
spot = null // OK
spot = undefined // Error
spot = 123 // Error
那 null 和 undefined 在 TypeScript的使用情境是什麼呢?
官網對於 null 和 undefined 的使用情境介紹不多,另外看了一些關於 null 和 undefined 的文件例如 dev.to這篇文章和TypeScript Deep Dive,發現在 null 和 undefined 的使用上有各種派別,有些派別使用 null 和 undefined 兩者,有些僅使用 null 或 undefined 其中之一,各有優缺點。
TypeScript 團隊建議只用 undefined 不用 null,Douglas Crockford 認為使用 null 不是一個好主意,應該只用 undefined 就好。然而,要注意的是 JSON 格式只支援 null 不支援 undefined,因此,在處理 JSON 格式的時候可能就需要使用 null。
補充:根據官方 JSON 標準(ECMA-404, Section 5),JSON value 可以是物件、陣列、數字、字串、布林值(true/false)和 null。JSON value 不支援 undefined,所以不能宣告 {“key”:undefined} ,但{“key”:”undefined”} 可被接受因為 ”undefined” 這樣的寫法是字串。
使用情境舉例來說,可以使用複合型別告訴編譯器哪些變數可以是空值
type User = {
firstName: string;
lastName: string | undefined;
};
let jane: User = { firstName: "Jane", lastName: undefined };
let john: User = { firstName: "John", lastName: "Doe" };
在填資料時,允許使用者可以不用填姓,可以寫成上方的程式碼。但事實上,在 TS 中更常見的是透過在名稱後方加上?使之成為可選屬性,如此,lastName 屬性就可要可不要。
type User = {
firstName: string;
lastName?: string;
};
// 可以放入字串型別的值
let john: User = { firstName: "John", lastName: "Doe" };
// 可以讓值為 undefined
let jane: User = { firstName: "Jane", lastName: undefined };
// 或者就不要 lastname 這個屬性了
let jake: User = { firstName: "Jake" };
至於之後會介紹的 void 和 null、undefined很相似,之後會再細細比較。
symbol的值是透過 Symbol建構函式創建的
let sym1 = Symbol();
let sym2 = Symbol("key"); // 可選字串key
但symbol是不可改變且唯一的
let sym2 = Symbol("key");
let sym3 = Symbol("key");
sym2 === sym3; // false
symbol 可以像字串一樣作為物件屬性的key值
let sym = Symbol();
let obj = {[sym]: "value"};
console.log(obj[sym]); // "value"
除了使用者定義的symbol外,還有一些內建symbols( built-in symbols),用來表示語言內部的行為,列表請參見官網,這邊不多做研究討論。
註:若要使用 symbol,在 tsconfig.json 檔中要設定 lib: ["es2015"],否則會報錯(參考此文章)
今天的文章介紹了 TS 中的原始型別(Primitive Types),包括數字(number)、字串(string)、布林值(boolean)、undefined、null 和 symbol,這些型別都是原生 JS 所支援的。字串、數字和布林值都很常見,Undefined 、 Null 和 Symbol 使用情境較不明確,或許等到之後開始實作應用後可以有更多心得,再來補充分享。
如有錯誤的地方,還請留言告知,我會盡快修改調整,感謝:)
參考資料:
TypeScript官網
Non-Nullable Types in TypeScript
TypeScript Deep Dive
Symbols in JavaScript and TypeScript